﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _09_FloatToBinary
{
    class Program
    {
        static void Main(string[] args)
        {
            //USEFUL!!! http://www.h-schmidt.net/FloatConverter/IEEE754.html
            decimal decimalNum;
            float floatTemp;
            do
            {
                Console.WriteLine("Enter float number");
            }
            while (!decimal.TryParse(Console.ReadLine(), out decimalNum)||!float.TryParse(decimalNum.ToString(),out floatTemp));
            byte binarySign;
            sbyte sign;
            int exponent;
            decimal mantissa;
            binarySign = (decimalNum < 0) ?(byte) 1 : (byte)0;
            sign= (decimalNum < 0) ? (sbyte)-1 : (sbyte)1;
            int absoluteInteger = (int)Math.Abs(decimalNum);
            decimal absoluteDecimal = (decimal)(Math.Abs(decimalNum) - absoluteInteger);
            StringBuilder binaryMantissa = CalcMantissa(absoluteDecimal);
            exponent = CalcExponent((decimal)Math.Abs(decimalNum), binaryMantissa);
            string binaryExponent = (decimalNum==0.0m)?Convert.ToString(0, 2).PadLeft(8, '0'):Convert.ToString(exponent + 127, 2).PadLeft(8, '0');
            binaryMantissa = Normalize(Convert.ToString(absoluteInteger,2), binaryMantissa, exponent);
            Console.WriteLine("Binary Representation: Sign {0} Exponent  {1} Mantissa {2}", binarySign, binaryExponent, binaryMantissa.ToString().PadRight(23, '0'));
            mantissa =(decimal)Math.Abs(decimalNum /(decimal)(Math.Pow(2,exponent)));
            Console.WriteLine("Real Sign {0} Real Exponent {1} Real Mantissa {2:F7}",sign, (decimalNum==0.0m)?-127:exponent, mantissa);
            
        }

        private static StringBuilder Normalize(string binaryExponent, StringBuilder binaryMantissa, int exponent)
        {
            int startIndex = binaryExponent.Length-exponent;
            StringBuilder binary = new StringBuilder(binaryExponent+binaryMantissa);
            StringBuilder normalized = new StringBuilder( binary.ToString().Substring(startIndex));
            if (normalized.Length > 23)
            {
                char lastsymbol = normalized[23];
                normalized = new StringBuilder( normalized.ToString().Substring(0, 23));
                if (lastsymbol=='1')
                {
                    int cntCarry = normalized.Length - 1;
                    while (cntCarry > 0)
                    {
                        if (normalized[cntCarry] == '1')
                        {
                            normalized[cntCarry] = '0';
                        }
                        else
                        {
                            normalized[cntCarry] = '1';
                            break;
                        }
                        cntCarry--;
                    }   
                }
               
            }
            return normalized;
        }

        private static StringBuilder CalcMantissa(decimal absoluteDecimal)
        {
            StringBuilder binaryMantissa = new StringBuilder();
            decimal currentNum = absoluteDecimal;
            int mantissaCnt = 1;
            int leadingZeroCnt =1;
            bool setBitFound = false;
            while (currentNum!=0.0m)
            {
                currentNum *= 2;
                if (currentNum<1)
                {
                    binaryMantissa.Append('0');
                }
                else
                {
                    binaryMantissa.Append('1');
                    currentNum -= 1;
                    setBitFound = true;
                }
                mantissaCnt++;
                if (!setBitFound)
                {
                    leadingZeroCnt++;
                }
                if ((mantissaCnt>23+leadingZeroCnt)||(leadingZeroCnt>=24))
                {
                    if (currentNum*2>1)
                    {
                        int cntCarry = binaryMantissa.Length - 1;
                        while (cntCarry>0)
                        {
                            if ( binaryMantissa[cntCarry] == '1')
                            {
                                binaryMantissa[cntCarry] = '0';
                            }
                            else
                            {
                                binaryMantissa[cntCarry] = '1';
                                break;
                            }
                            cntCarry--;
                        }   
                    }
                    break;
                }
            }
            return binaryMantissa;
        }

        private static int CalcExponent(decimal integer, StringBuilder binaryMantissa)
        
        {
            if (integer >= 2)
            {
                int absoluteInteger = (int)Math.Abs(integer);
                int counter = 1;
                while (true)
                {
                    if (counter > absoluteInteger)
                    {
                        counter /= 2;
                        break;
                    }
                    counter *= 2;
                }
                return (int)Math.Log(counter, 2);
            }
            else if (integer >0 && integer<1)
            {
                int negativeCnt = -1;
                foreach (var bit in binaryMantissa.ToString())
                {
                    if (bit=='1')
                    {
                        break;
                    }
                    negativeCnt--;
                }
                return negativeCnt;
            }
            else 
            {
                return 0;
            }
        }
    }
}
